<style>
  #payapl-card-submit-button {
    width: 100%;
    height: 48px;
    background: #ffc439;
    font-size: 16px;
    color: #ffffff;
    text-align: center;
    border-radius: 4px;
    cursor: pointer;
  }

  #paypal-button-container {
    width: 100%;
    height: 48px;
    text-align: center
  }

  /* CSS */
  apple-pay-button {
    --apple-pay-button-width: 100%;
    --apple-pay-button-height: 30px;
    --apple-pay-button-border-radius: 5px;
    --apple-pay-button-padding: 9px 0px;
  }

  apple-pay-button:hover {
    opacity: 0.8;
  }
</style>

<div class="payment_method_content">
  <ul>
    <li>
      <div class="order_radio_box">
        <label class="radio_label payment_methods-item" style="height: auto;"
          for="paypal-payment-type">
          <input class="order_radio payment_item" autocomplete="off" type="radio"
            id="paypal-payment-type" name="paypal-payment" value="button" />
          <div class="payment_methods-label">
            <span class="radio_icon"></span>
            <span>
              <div style="height:18px;line-height: 18px;">paypal</div>
            </span>
          </div>
        </label>
      </div>
      <div class="payment_methods_down " style="padding: 15px;">
        <div id="paypal-button-container"></div>
      </div>
    </li>
    <li>
      <div class="order_radio_box">
        <label class="radio_label payment_methods-item" style="height: auto;"
          for="paypal-payment-card">
          <input class="order_radio payment_item" autocomplete="off" type="radio"
            id="paypal-payment-card" name="paypal-payment" value="card" />
          <div class="payment_methods-label">
            <span class="radio_icon"></span>
            <span>
              <div style="height:18px;line-height: 18px;">paypal card</div>
            </span>
          </div>
        </label>
      </div>
      <div class="payment_methods_down " style="padding: 15px;">
        <div id="payapl-card-warp" style="display: flex;flex-direction: column;">
          <div id="payapl-card-vault-list"></div>
          <div id="payapl-card-form" style="width: 100%;display: none;box-sizing: border-box;"
            class="card_container">
            <div id="card-name-field-container"></div>
            <div id="card-number-field-container" style="margin-top: 15px;height:48px"></div>
            <div style="display: flex;margin-top: 15px;">
              <div style="flex: 1;height:48px;" id="card-expiry-field-container"></div>
              <div style="width:15px;"></div>
              <div style="flex: 1;height:48px;" id="card-cvv-field-container"></div>
            </div>
          </div>
          <button id="payapl-card-submit-button" style="margin-top: 15px;" type="button">Pay
            Card</button>
        </div>
      </div>
    </li>
    <li>
      <div class="order_radio_box">
        <label class="radio_label payment_methods-item" style="height: auto;"
          for="paypal-payment-goolepay">
          <input class="order_radio payment_item" autocomplete="off" type="radio"
            id="paypal-payment-goolepay" name="paypal-payment" value="goolepay" />
          <div class="payment_methods-label">
            <span class="radio_icon"></span>
            <span>
              <div style="height:18px;line-height: 18px;">goolepay</div>
            </span>
          </div>
        </label>
      </div>
      <div class="payment_methods_down " style="padding: 15px;">
        <div id="paypal-google-container" style="width: 100%;height: 48px;"></div>
      </div>
    </li>

    <li>
      <div class="order_radio_box">
        <label class="radio_label payment_methods-item" style="height: auto;"
          for="paypal-payment-applepay">
          <input class="order_radio payment_item" autocomplete="off" type="radio"
            id="paypal-payment-applepay" name="paypal-payment" value="applepay" />
          <div class="payment_methods-label">
            <span class="radio_icon"></span>
            <span>
              <div style="height:18px;line-height: 18px;"> applepay</div>
            </span>
          </div>
        </label>
      </div>
      <div class="payment_methods_down " style="padding: 15px;">
        <div id="paypal-applepay-container" style="width: 100%;margin-top: 15px;"></div>
      </div>
    </li>
  </ul>
</div>
<script>
  $(function () {

    $('input[name="paypal-payment"]').change(function () {
      $('.payment_methods_down').removeClass('payment_methods_on');
      $(this).parents('li').find('.payment_methods_down').addClass('payment_methods_on');
    })

    let paypalSDKURL = 'https://www.paypal.com/sdk/js?components=buttons,messages,card-fields,applepay,googlepay&client-id=AbDVgdowL4PlqhVii4AqmDg6b3FylnBtPp8gxsBpCisKRHy983Jnj-ABVKiFtq1tdS53KUFCdyzA5-Ue';

    function createPaypalCard() {

      function createCardVaultHtml(list) {
        return list.map((item, index) => {
          return ` <label for="${item.id}" ${index === 0 ? 'checked' : ''} style="display: flex;align-items: center;font-size: 14px;">
            <input type="radio" name="payapl-card" value="${item.value}" id="${item.id}">
            <span style="margin-left: 8px;">${label}</span>
          </label>`
        }).join('');
      }

      //创建paypal卡号
      function createPaypalCardVault(list) {
        if (!list || !Array.isArray(list) || !list.length) {
          console.log('list is null');
          $("#payapl-card-form").show();
          return
        }
        list = list.push({
          id: "payapl-card-input",
          value: "",
          label: "use a new pyament method"
        })
        let html = createCardVaultHtml(list);
        $("#payapl-card-vault-list").append(html);

      }
      createPaypalCardVault([])

      let buttonLoad;
      function getPayPalCardVaultId() {
        return $("input[name='payapl-card']:checked").val() || '';
      }

      async function createOrderCallback(data) {
        try {
          const response = await fetch('/checkouts/ecpayment/paypalcompletepayments/ECOrderPay?is_ajax=1&payment_methods=card&order_number={$order_number}', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({ vault_id: getPayPalCardVaultId() }),
          }).then((res) => res.json());

          // vault_id 支付跳转页面
          if (response.data.return_url) {
            location.href = response.data.return_url;
            return
          }

          if (response.data.id) {
            return response.data.id;
          } else {
            buttonLoad && buttonLoad.close();
            moi.message({ content: response.data.L_LONGMESSAGE0, type: "error" })
          }
        } catch (error) {
          moi.message({ content: error, type: "error" })
          console.error(error);
        }
      }

      async function onApproveCallback(data, actions) {

        try {
          console.log("onApproveCallback");
          console.log(data);
          const response = await fetch(`{$url}&token=` + data.orderID, {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
          });

          const orderData = await response.json();
          if (orderData.data.redirect_url) {
            location.href = orderData.data.redirect_url
          } else {
            buttonLoad && buttonLoad.close();
            moi.message({ content: orderData.data.msg, type: "error" })
          }
        } catch (error) {
          moi.message({ content: error, type: "error" })
          console.error(error);
        }
      }
      const cardField = window.paypal.CardFields({
        createOrder: createOrderCallback,
        onApprove: onApproveCallback,
      });

      if (cardField.isEligible()) {
        const style = {
          "body": {
            "padding": "0"
          },
          'input': {
            'font-size': '16px',
            'color': '#333333',
            'border': '1px solid #d9d9d9',
            "padding": "12px"
          },
          ':focus': {
            'color': 'blue',
            "box-shadow": "none"
          },
          '.valid': {
            'color': '#333333'
          },
          '.invalid': {
            'color': 'red'
          }
        }
        const nameField = cardField.NameField({
          style
        });
        nameField.render("#card-name-field-container");

        const numberField = cardField.NumberField({ style });
        numberField.render("#card-number-field-container");

        const cvvField = cardField.CVVField({ style });
        cvvField.render("#card-cvv-field-container");

        const expiryField = cardField.ExpiryField({ style });
        expiryField.render("#card-expiry-field-container");

        document
          .getElementById("payapl-card-submit-button")
          .addEventListener("click", () => {
            buttonLoad = moi.nodeShowLoading("#payapl-card-submit-button", "#fff")
            if (getPayPalCardVaultId()) {
              createOrderCallback()
              return
            }
            cardField.submit({}).catch((error) => { buttonLoad && buttonLoad.close(); });
          });
      } else {
        moi.message({ content: '账号 paypal card 不支持', type: "error" })
        document.querySelector("#payapl-card-form").style = "display: none";
      }

    }

    function createPaypalButton() {
      paypal.Buttons({
        style: {
          height: 48,
          layout: 'vertical',  // horizontal | vertical
        },
        createOrder: function (data, actions) {
          try {
            return fetch('/checkouts/ecpayment/paypalcompletepayments/ECOrderPay?is_ajax=1&order_number=$order_number', {
              method: 'POST'
            }).then(function (res) {
              return res.json();
            }).then(function (data) {
              if (data.status) {
                paypal_redirect_url = data.data.return_url;
                return data.data.paypal_order_id;
              }
              else {
                if (data.data.L_ERRORCODE0 == 10736) {
                  location.href = '$contact_edit_url&_ref=$ref' + '&payment_failed_msg=' + data.data.L_LONGMESSAGE0;
                }
                moi.message({ content: res.data.L_LONGMESSAGE0, type: "error" })
                return false;
              }
            });
          } catch (error) {
            moi.message({ content: "create order error", type: "error" })
            console.error(error)
          }

        },
        onApprove: function (data, actions) {
          try {
            return fetch(paypal_redirect_url, {
              method: 'POST'
            }).then(function (res) {
              return res.json();
            }).then(function (res) {
              if (res.code > 0) {
                moi.message({ content: res.data.L_LONGMESSAGE0, type: "error" })
              }
              else {
                location.href = res.data.redirect_url;
              }
            });
          } catch (error) {
            moi.message({ content: "onApprove error", type: "error" })
            console.error(error)
          }

        }
      }).render('#paypal-button-container');
    }

    function createPaypalGooglePayment() {

      /**
       * An initialized google.payments.api.PaymentsClient object or null if not yet set
       * An initialized paypal.Googlepay().config() response object or null if not yet set
       *
       * @see {@link getGooglePaymentsClient}
       */
      let paymentsClient = null, googlepayConfig = null;

      /**
       * 
       * @returns Fetch the Google Pay Config From PayPal 
       */
      async function getGooglePayConfig() {
        if (googlepayConfig === null) {
          googlepayConfig = await paypal.Googlepay().config();
          console.log(" ===== Google Pay Config Fetched ===== ");

        }
        return googlepayConfig;
      }

      /**
       * Configure support for the Google Pay API
       *
       * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|PaymentDataRequest}
       * @returns {object} PaymentDataRequest fields
       */
      async function getGooglePaymentDataRequest() {
        const { allowedPaymentMethods, merchantInfo, apiVersion, apiVersionMinor, countryCode } = await getGooglePayConfig();
        const baseRequest = {
          apiVersion,
          apiVersionMinor
        }
        const paymentDataRequest = Object.assign({}, baseRequest);

        paymentDataRequest.allowedPaymentMethods = allowedPaymentMethods;
        paymentDataRequest.transactionInfo = getGoogleTransactionInfo(countryCode);
        paymentDataRequest.merchantInfo = merchantInfo;

        paymentDataRequest.callbackIntents = ["PAYMENT_AUTHORIZATION"];

        return paymentDataRequest;
      }

      /**
       * Handles authorize payments callback intents.
       *
       * @param {object} paymentData response from Google Pay API after a payer approves payment through user gesture.
       * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentData object reference}
       *
       * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentAuthorizationResult}
       * @returns Promise<{object}> Promise of PaymentAuthorizationResult object to acknowledge the payment authorization status.
       */
      function onPaymentAuthorized(paymentData) {
        return new Promise(function (resolve, reject) {
          processPayment(paymentData)
            .then(function () {
              resolve({ transactionState: 'SUCCESS' });
            })
            .catch(function () {
              resolve({ transactionState: 'ERROR' });
            });
        });
      }

      /**
       * Return an active PaymentsClient or initialize
       *
       * @see {@link https://developers.google.com/pay/api/web/reference/client#PaymentsClient|PaymentsClient constructor}
       * @returns {google.payments.api.PaymentsClient} Google Pay API client
       */
      function getGooglePaymentsClient() {
        if (paymentsClient === null) {
          paymentsClient = new google.payments.api.PaymentsClient({
            environment: 'TEST',
            paymentDataCallbacks: {
              onPaymentAuthorized: onPaymentAuthorized
            }
          });
        }
        return paymentsClient;
      }

      /**
       * Initialize Google PaymentsClient after Google-hosted JavaScript has loaded
       *
       * Display a Google Pay payment button after confirmation of the viewer's
       * ability to pay.
       */
      async function onGooglePayLoaded() {
        const paymentsClient = getGooglePaymentsClient();
        const { allowedPaymentMethods, apiVersion, apiVersionMinor } = await getGooglePayConfig();
        paymentsClient.isReadyToPay({ allowedPaymentMethods, apiVersion, apiVersionMinor })
          .then(function (response) {
            if (response.result) {
              addGooglePayButton();
            }
          })
          .catch(function (err) {
            // show error in developer console for debugging
            console.error(err);
          });
      }

      /**
       * Add a Google Pay purchase button alongside an existing checkout button
       *
       * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#ButtonOptions|Button options}
       * @see {@link https://developers.google.com/pay/api/web/guides/brand-guidelines|Google Pay brand guidelines}
       */
      function addGooglePayButton() {
        const paymentsClient = getGooglePaymentsClient();
        const button =
          paymentsClient.createButton({
            buttonColor: 'default',
            buttonType: 'checkout',
            buttonSizeMode: 'fill',
            onClick: onGooglePaymentButtonClicked
          });
        document.getElementById('paypal-google-container').appendChild(button);
      }

      /**
       * Provide Google Pay API with a payment amount, currency, and amount status
       *
       * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo|TransactionInfo}
       * @returns {object} transaction info, suitable for use as transactionInfo property of PaymentDataRequest
       */
      function getGoogleTransactionInfo(countryCode) {
        // var params = moi.getPageStorage('product_params{{ pay_id }}');
        return {
          countryCode: countryCode,
          currencyCode: oemcart_currency.standard_code,
          totalPriceStatus: "FINAL",
          totalPrice: '10.00',
          totalPriceLabel: "Total"
        };
      }


      /**
       * Show Google Pay payment sheet when Google Pay payment button is clicked
       */
      async function onGooglePaymentButtonClicked() {
        // var params = moi.getPageStorage('product_params{{ pay_id }}');
        // var ret = moi.onEvent("payVerified", { property: [], product: params, code: 200 });
        // if (ret.params.code !== 200) {
        //   return false
        // }
        const paymentDataRequest = await getGooglePaymentDataRequest();
        const paymentsClient = getGooglePaymentsClient();
        paymentsClient.loadPaymentData(paymentDataRequest);
      }


      function getProductCartParam() {
        var params = moi.getPageStorage('product_params{{ pay_id }}');
        var ret = moi.onEvent("payVerified", { property: [], product: params, code: 200 });

        var product_selected = {
          product_id: params.product_id,
          sku_code: params.sku_code,
          quantity: params.quantity,
          data_from: moi.getUrlParam("data_from") || "{{data_from}}",
          property: ret.params.property

        }
        return encodeURIComponent(JSON.stringify(product_selected));
      }

      /**
       * Process payment data returned by the Google Pay API
       *
       * @param {object} paymentData response from Google Pay API after user approves payment
       * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentData|PaymentData object reference}
       */
      async function processPayment(paymentData) {
        const resultElement = document.getElementById("result");
        const modal = document.getElementById("resultModal");
        resultElement.innerHTML = "";
        try {
          const { data } = await fetch('/checkouts/ecpayment/paypalcompletepayments/ECPay?is_ajax=1&payment_methods=google&payment_id={{ payment.id }}&cart_param=' + getProductCartParam() + '&_ref=' + window.location.href, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            }
          }).then((res) => res.json());
          console.log(" ===== Order Created ===== ");
          /** Approve Payment */
          const { status } = await paypal.Googlepay().confirmOrder({
            orderId: data.id,
            paymentMethodData: paymentData.paymentMethodData
          });
          console.log(" ===== confirmOrder status ===== ", status)
          if (status === 'PAYER_ACTION_REQUIRED') {
            console.log(" ===== Confirm Payment Completed Payer Action Required ===== ")
            paypal.Googlepay().initiatePayerAction({ orderId: data.id }).then(async () => {
              location.href = data.return_url;
            })
          } else {
            location.href = data.return_url;
          }
          return { transactionState: 'SUCCESS' }
        } catch (err) {
          return {
            transactionState: 'ERROR',
            error: {
              message: err.message
            }
          }
        }
      }



      moi.createScript("https://pay.google.com/gp/p/js/pay.js", function () {
        if (google && paypal.Googlepay) {
          onGooglePayLoaded().catch(console.log);
        }
      })
    }

    function createApplePayButton() {
      async function setupApplepay() {
        const applepay = paypal.Applepay();
        const {
          isEligible,
          countryCode,
          currencyCode,
          merchantCapabilities,
          supportedNetworks,
        } = await applepay.config();

        if (!isEligible) {
          throw new Error("applepay is not eligible");
        }

        document.getElementById("paypal-applepay-container").innerHTML =
          '<apple-pay-button id="btn-appl" buttonstyle="black" type="buy" locale="en">';

        document.getElementById("btn-appl").addEventListener("click", onClick);

        async function onClick() {
          console.log({ merchantCapabilities, currencyCode, supportedNetworks })

          const paymentRequest = {
            countryCode,
            currencyCode: oemcart_currency.standard_code,
            merchantCapabilities,
            supportedNetworks,
            requiredBillingContactFields: [
              "name",
              "phone",
              "email",
              "postalAddress",
            ],
            requiredShippingContactFields: [
            ],
            total: {
              label: "Total",
              amount: params.price.toString(),
              type: "final",
            },
          };

          // eslint-disable-next-line no-undef
          let session = new ApplePaySession(4, paymentRequest);

          session.onvalidatemerchant = (event) => {
            applepay
              .validateMerchant({
                validationUrl: event.validationURL,
              })
              .then((payload) => {
                session.completeMerchantValidation(payload.merchantSession);
              })
              .catch((err) => {
                console.error(err);
                session.abort();
              });
          };

          session.onpaymentmethodselected = () => {
            session.completePaymentMethodSelection({
              newTotal: paymentRequest.total,
            });
          };

          session.onpaymentauthorized = async (event) => {
            try {
              /* Create Order on the Server Side */
              const { data } = await fetch('/checkouts/ecpayment/paypalcompletepayments/ECPay?is_ajax=1&payment_methods=applepay&payment_id={{ payment.id }}&cart_param=' + getProductCartParam() + '&_ref=' + window.location.href, {
                method: 'POST',
                headers: {
                  'Content-Type': 'application/json'
                }
              }).then((res) => res.json());
              /**
               * Confirm Payment 
               */
              await applepay.confirmOrder({ orderId: data.id, token: event.payment.token, billingContact: event.payment.billingContact, shippingContact: event.payment.shippingContact });
              location.href = data.return_url;
              session.completePayment({
                status: window.ApplePaySession.STATUS_SUCCESS,
              });
            } catch (err) {
              console.error(err);
              session.completePayment({
                status: window.ApplePaySession.STATUS_FAILURE,
              });
            }
          };

          session.oncancel = () => {
            console.log("Apple Pay Cancelled !!")
          }

          session.begin();
        }
      }

      moi.createScript("https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js", function () {
        if (ApplePaySession?.supportsVersion(4) && ApplePaySession?.canMakePayments()) {
          setupApplepay().catch(console.error);
        }
      })
    }

    moi.createScript(paypalSDKURL, function () {
      if (window.paypal) {
        createPaypalCard();
        createPaypalButton();
        createPaypalGooglePayment();
        createApplePayButton();
      }
    })


  })
</script>